package com.didi.virtualapk.hooker

import com.android.build.gradle.api.ApkVariant
import com.android.build.gradle.tasks.MergeSourceSetFolders
import com.android.ide.common.res2.AssetSet
import com.didi.virtualapk.collector.dependence.AarDependenceInfo
import com.didi.virtualapk.utils.Log
import com.didi.virtualapk.utils.Reflect
import org.gradle.api.Project

import java.util.function.Predicate
import java.util.function.Supplier

/**
 * Remove the asset directory included in the excluded library before mergeAssets task
 *
 * @author zhengtao
 */
class MergeAssetsHooker extends GradleTaskHooker<MergeSourceSetFolders> {

    public MergeAssetsHooker(Project project, ApkVariant apkVariant) {
        super(project, apkVariant)
    }

    @Override
    String getTaskName() {
        return scope.getTaskName('merge', 'Assets')
    }

    /**
     * Remove the element(AssetSet) generated by the stripped dependenceInfos in the task inputDirectorySets
     * @param task Gradle task of mergeAssets
     */
    @Override
    void beforeTaskExecute(MergeSourceSetFolders task) {

        Set<String> strippedAssetPaths = vaContext.stripDependencies.collect {
            if (it instanceof AarDependenceInfo) {
                return it.assetsFolder.path
            }
            return ''
        }

        Reflect reflect = Reflect.on(task)
        reflect.set('assetSetSupplier', new FixedSupplier(this, reflect.get('assetSetSupplier'), strippedAssetPaths))
    }

    @Override
    void afterTaskExecute(MergeSourceSetFolders task) {
    }
    
    static class FixedSupplier implements Supplier<List<AssetSet>> {

        MergeAssetsHooker hooker
        Supplier<List<AssetSet>> origin
        Set<String> strippedAssetPaths
        
        FixedSupplier(MergeAssetsHooker hooker, Supplier<List<AssetSet>> origin, Set<String> strippedAssetPaths) {
            this.hooker = hooker
            this.origin = origin
            this.strippedAssetPaths = strippedAssetPaths
        }
        
        @Override
        List<AssetSet> get() {
            List<AssetSet> assetSets = origin.get()
            assetSets.removeIf(new Predicate<AssetSet>() {
                @Override
                boolean test(AssetSet assetSet) {
                    boolean ret = strippedAssetPaths.contains(assetSet.sourceFiles.get(0).path)
                    if (ret) {
                        Log.i 'MergeAssetsHooker', "Stripped asset of artifact: ${assetSet} -> ${assetSet.sourceFiles.get(0).path}"
                    }
                    return ret
                }
            })
            hooker.mark()
            return assetSets
        }
    }
}